<template>
  <section class="app-dialog" v-if="data.showContainer" @click="coverHandle">
    <section class="app-dialog-container" :style="data.containerStyle" :class="{open:data.showComponent}">
      <header class="app-dialog-header" :style="headerStyle">
        <div class="app-dialog-title" v-if="!config.title">
          <slot name="title">提示</slot>
        </div>
        <div class="app-dialog-title" v-else>
          {{ config.title }}
        </div>
        <div class="app-dialog-close iconfont icon-close" v-if="!config.hideCloseBtn" @click.stop="hide"></div>
      </header>
      <main class="app-dialog-main" ref="container">
        <slot>内容区域</slot>
      </main>
    </section>
  </section>
</template>

<script lang="ts" setup>

import { computed, ComputedRef, nextTick, onUnmounted, reactive, Ref, ref, watch } from 'vue'

interface Props {
  show: boolean
  width?: string
  showCover?: boolean
  hideCloseBtn?: boolean
  title?: string
  closeOnClickCover?: boolean
}

interface Data {
  showContainer: boolean;
  showComponent: boolean;
  containerStyle: string;
  defaultOptions: {
    show: boolean
    showCover: boolean;
    closeOnClickCover: boolean
    hideCloseBtn: boolean
    titleHeight: number
    titleFontSize: number
    top: string
    title: string
    titleBackground: string
  }
}

const props = withDefaults(defineProps<Props>(), {
  show: false,
  width: '',
  showCover: true,
  hideCloseBtn: false,
  closeOnClickCover: true
})

const emit = defineEmits(['hide', 'update:show', 'show'])

const data = reactive<Data>({
  showContainer: false,
  showComponent: false,
  containerStyle: '',
  defaultOptions: {
    show: false,
    showCover: true, // 是否展示蒙层
    closeOnClickCover: false, // 点击蒙层是否关闭弹窗
    hideCloseBtn: false, // 是否隐藏关闭图标
    titleHeight: 44, // 标题所占高度
    titleFontSize: 18,
    top: '100px',
    title: '',
    // titleBackground: 'linear-gradient(90deg, rgba(95, 95, 95, 1) 0%, rgba(66, 66, 66, 1) 100%)' // 标题部分的背景
    titleBackground: '#fff' // 标题部分的背景
  }
})

const config: ComputedRef<Props & Data['defaultOptions']> = computed(() => {
  return { ...data.defaultOptions, ...props }
})

const container = ref<HTMLElement>() as Ref<HTMLElement>

onUnmounted(() => {
  document.body.style.overflow = ''
})

const hide = () => {
  data.showComponent = false
  setTimeout(() => {
    data.showContainer = false
  }, 200)
  document.body.style.overflow = ''
  emit('update:show', false)
  emit('hide')
}

const coverHandle = (event: any) => {
  if (config.value.closeOnClickCover && event?.target?.className === 'app-dialog') {
    hide()
  }
}
const headerStyle = computed(() => {
  return `height:${config.value.titleHeight}px;background:${config.value.titleBackground};font-size:${config.value.titleFontSize}px;`
})
const show = () => {
  data.showContainer = true
  nextTick(() => {
    container.value.style.width = config.value.width || '350px'
    data.containerStyle = `width:${container.value.style.width};height:auto;margin:${config.value.top} auto;`
  })
  setTimeout(() => {
    data.showComponent = true
  }, 20)
  document.body.style.overflow = 'hidden'
  emit('show')
}

watch(() => props.show, (val) => {
  if (val) {
    show()
    return
  }
  hide()
})
defineExpose({
  hide
})
</script>

<style scoped lang="scss">
.app-dialog {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2000;
  background: rgba(0, 0, 0, 0.25);
  overflow: auto;
}

//.app-dialog-cover {
//position: fixed;
//width: 100%;
//height: 100%;
//top: 0;
//left: 0;
//right: 0;
//bottom: 0;
//z-index: 1000;
//background: rgba(0, 0, 0, 0.3);
//}

.app-dialog-container {
  opacity: 0;
  transition: transform .2s ease-out, opacity .2s ease-out;
  border-radius: 4px;
  z-index: 2001;
  background: #ffffff;
  transform: scale(0.5, 0.5);

  &.open {
    opacity: 1;
    transform: scale(1, 1);
  }

  .app-dialog-header {
    user-select: none;
    width: 100%;
    border-radius: 8px 8px 0 0;
    box-sizing: border-box;
    //background: #333;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 2px rgba(0,0,0,0.1);
    .app-dialog-title {
      color: #333;
    }

    .app-dialog-close {
      cursor: pointer;
      position: absolute;
      top: 50%;
      margin-top: -10px;
      right: 20px;
      font-size: 20px;
      color: #333;
    }
  }

  .app-dialog-main {
    min-width: 350px;
    min-height: 100px;
    background: #ffffff;
    width: 100%;
    box-sizing: border-box;
    border-radius: 0 0 8px 8px;
    margin-bottom: 20px;
    padding: 20px;
  }
}
</style>
